import json
import os
import re
import subprocess
import time

import requests
from lxml import etree

print("所有视频将保存在  D:/B站视频")
if not os.path.exists('D:/B站视频'):
    os.mkdir('D:/B站视频')

while True:
    url = input("请粘贴视频播放链接：")
    time.sleep(1)
    print("正在下载，请稍后......")
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36',
        'Referer': 'https://www.bilibili.com/'
    }
    # 发送请求
    response = requests.get(url=url, headers=headers)
    # 获取网页源代码
    info = re.findall('window.__playinfo__=(.*?)</script>', response.text)[0]

    # 获取视频和音频播放链接
    video_url = json.loads(info)["data"]["dash"]["video"][0]["baseUrl"]
    audio_url = json.loads(info)["data"]["dash"]["audio"][0]["baseUrl"]

    # 对网页源代码数据生成树结构
    html = etree.HTML(response.text)
    # 爬取视频名称
    filename = html.xpath('//*[@id="viewbox_report"]/h1/text()')[0]
    # 正则匹配，替换非法命名字符
    filename = re.sub('[\\\/|":*? ]', '-', filename)
    name = filename + '(合成)'

    # 视频和音频字节化
    v_con = requests.get(url=video_url, headers=headers).content
    a_con = requests.get(url=audio_url, headers=headers).content

    # 保存视频和音频
    print("开始下载音频部分...")
    try:
        # 保存音频
        with open(f'D:/B站视频/{filename}.mp3', 'wb') as f:
            f.write(a_con)
            print("已下载音频部分！")

    # 如果保存失败，则多次尝试保存
    except:
        index = 0
        while index < 3:  # 尝试3次
            print(f'正在重试第{index + 1}次！')
            try:
                with open(f'D:/B站视频/{filename}.mp3', 'wb') as f:
                    f.write(a_con)
                    print("已下载音频部分！")
            except:
                print("音频部分下载失败！")
            index += 1

    # 保存视频，操作与保存音频一样
    print("开始下载视频部分...")
    try:
        with open(f'D:/B站视频/{filename}.mp4', 'wb') as f:
            f.write(v_con)
            print("已下载视频部分！")
    except:
        index = 0
        while index < 3:
            print(f'正在重试第{index + 1}次！')
            try:
                with open(f'D:/B站视频/{filename}.mp4', 'wb') as f:
                    f.write(v_con)
                    print("已下载视频部分！")
            except:
                print("视频部分下载失败！")
            index += 1

    # 通过cmd命令，用ffmpeg来合并视频和音频
    cmd = f'ffmpeg - i {filename}.mp4 -i {filename}.mp3 -c:v copy -c:a copy {name}.mp4'
    os.system(cmd)
    cmd = f'ffmpeg -i D:/B站视频/{filename}.mp4 -i D:/B站视频/{filename}.mp3 -c:v copy -c:a copy D:/B站视频/{name}.mp4'
    subprocess.run(cmd, shell=True)

    # 合并完后删除原有的视频和音频，只保留合并后的{name}.mp4文件
    os.remove(f'D:/B站视频/{filename}.mp3')
    os.remove(f'D:/B站视频/{filename}.mp4')
    print("下载完成！！！")
